package com.docking.heylo.service.impl;

import cn.hutool.http.HttpUtil;
import com.docking.heylo.exception.GeneralException;
import com.docking.heylo.pojo.PayOrderPackage;
import com.docking.heylo.web.utils.MD5;
import com.github.pagehelper.util.StringUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

@Component
@Configuration
public class WeChatPayServerImpl {

    /***
     * 微信程序ID
     */
    private  final String APP_ID = "wx8ee32c8034818f92";

    /***
     * 微信商户帐号
     */
    private  final String MCHID = "1602816945";

    /***
     * 微信统一下单地址
     */
    private  final String UNIFORMORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    /***
     * 接口调用密钥
     */
    private  final String APIKEY = "inIPb3J8KFTnchKvdbpix2gk4BebN9si";

    private  final String appSecret = "5b126707b3022434ee8be15040140e12";


    public  final String FAIL     = "FAIL";
    public  final String SUCCESS  = "SUCCESS";

    /***
     * 创建支付订单
     *
     * @param order
     * @return
     */
    public  Map<String,Object> uniformorder(PayOrderPackage order){
        try {
            String                      randomStr   = getRandomString(18).toUpperCase();
            int                         money       = order.getAmount().multiply(new BigDecimal(100)).intValue();
            SortedMap<String,Object>    payParams   = new TreeMap<String, Object>(){{
                put("appid",            APP_ID);
                put("mch_id",           MCHID);                                                    // 商家帐号
                put("nonce_str",        randomStr);                                                // 随机字符串
                put("body",             order.getBody());                                          // 商品描述
                put("attach",           order.getSubject());
                put("fee_type",         "CNY");
                put("out_trade_no",     order.getTradeNo());                                       // 商户订单编号
                put("total_fee",        money);                                                    // 支付金额
//                put("total_fee", 1);                                                             // 支付金额 -- 默认分钱
                put("spbill_create_ip", order.getSpbillCreateIp());                                // 消费者IP
                put("notify_url",       order.getNotifyUrl());                                     // 回调地址
                put("trade_type",       "APP");                                                    // 交易类型APP
            }};
            payParams.put("sign", createSign(payParams));                                           // 数字签证
            String xml      = getRequestXML(payParams);

            //发送请求
            String content  = HttpUtil.post(UNIFORMORDER, xml);

            Map<String,String>  retInfo = readStringXmlOut(content) ;
            String              code    = retInfo.get("result_code");
            String msg= retInfo.get("err_code_des");
            if(code.equalsIgnoreCase(FAIL)){                  //创建支付单失败
                throw new GeneralException("创建支付失败：" + msg);
            }else if(code.equalsIgnoreCase(SUCCESS)){        //下单成功
                SortedMap<String, Object> params = new TreeMap<String, Object>(){{
                    put("appid",        APP_ID);
                    put("partnerid",    MCHID);
                    put("prepayid",     retInfo.get("prepay_id"));
                    put("package",      "Sign=WXPay");
                    put("noncestr",     retInfo.get("nonce_str"));
                    put("timestamp",    System.currentTimeMillis() / 1000 + "");
                }};
                params.put("sign", createSign(params));
                return new HashMap<String, Object>(){{
                    put("code",1);
                    put("msg","微信支付创建成功");
                    put("wxInfo",params);
                }};
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new GeneralException("创建支付失败");//支付失败
    }



    //拼接xml 请求路径
    public static String getRequestXML(SortedMap<String, Object> parame){
        StringBuffer buffer = new StringBuffer();
        buffer.append("<xml>");
        Set set = parame.entrySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            String key = (String)entry.getKey();
            String value = entry.getValue().toString();
            //过滤相关字段sign
            if("sign".equalsIgnoreCase(key)){
                buffer.append("<"+key+">"+"<![CDATA["+value+"]]>"+"</"+key+">");
            }else{
                buffer.append("<"+key+">"+value+"</"+key+">");
            }
        }
        buffer.append("</xml>");
        System.out.println(buffer.toString());
        return buffer.toString();
    }

    public static Map<String,String> readStringXmlOut(String xml) {
        Map<String,String> map = new HashMap<String,String>();
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(xml);            // 将字符串转为XML
            Element rootElt = doc.getRootElement();         // 获取根节点
            List<Element> list = rootElt.elements();        //获取根节点下所有节点
            for (Element element : list) {                  //遍历节点
                map.put(element.getName(), element.getText()); //节点的name为map的key，text为map的value
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    // 随机字符串生成
    public static String getRandomString(int length) { // length表示生成字符串的长度
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    //创建md5 数字签证
    public  String createSign(SortedMap<String, Object> parame) {
        StringBuffer    buffer      = new StringBuffer();
        for(String key : parame.keySet()){
            Object value = parame.get(key);
            if(null != value && StringUtil.isNotEmpty(value.toString())
                    && !"sign".equals(key)&& !"key".equals(key)
                    ){
                buffer.append(String.format("%s=%s&",key,value));
            }
        }
        buffer.append("key="+APIKEY);

        String signMe = MD5.getMD5(buffer.toString()).toUpperCase();

        System.out.println(String.format("微信支付1,参数[%s] | 签名[%s]",buffer.toString(),signMe));

        StringBuffer    buffer2      = new StringBuffer();
        Set             set         = parame.entrySet();
        Iterator        iterator    = set.iterator();
        while(iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            String key = (String)entry.getKey();
            Object value = entry.getValue()+"";
            if(null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)){
                buffer2.append(key+"="+value+"&");
            }
        }
        buffer2.append("key="+APIKEY);
        String sign = MD5.getMD5(buffer2.toString()).toUpperCase();
        System.out.println(String.format("微信支付2,参数[%s] | 签名[%s]",buffer.toString(),sign));
        return sign;
    }


    /***
     * 验证支付签名是否正确
     *
     * @param params
     * @return
     */
    public  boolean checkSignMd5(SortedMap<String,Object> params){
        String wxSign = (String) params.get("sign");
        params.remove("sign");

        String orSign = createSign(params);

        return orSign.equalsIgnoreCase(wxSign);
    }


}
